package com.webex.ta.hydra.gui.table;

import com.webex.ta.hydra.core.Command;

import javax.swing.*;
import javax.swing.border.AbstractBorder;
import javax.swing.event.CellEditorListener;
import javax.swing.event.ChangeEvent;
import javax.swing.event.EventListenerList;
import java.awt.*;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.geom.GeneralPath;

/**
 * Created by Cisco WebEx.
 * User: vegaz
 * Date: 2010-10-8
 * Time: 13:44:58
 */
public class AnnotationEditPane extends JPanel {
    private JTextField editor;
    private JComponent owner;
    private Command editingCmd;

    protected EventListenerList listenerList = new EventListenerList();
    transient protected ChangeEvent changeEvent = null;

    public AnnotationEditPane(JComponent owner) {
        super();
        this.owner = owner;
        this.setLayout(null);
        editor = new JTextField(10);
        editor.setBackground(new Color(249, 247, 142, 220));
        this.add(editor);
        this.setOpaque(false);
        editor.setBorder(new AnnotationEditPaneBorder());
        editor.addKeyListener(new KeyListener() {
            public void keyPressed(KeyEvent e) {
                if (e.getKeyChar() == KeyEvent.VK_ENTER && e.getModifiers() == 0) {
                    stopEdit();
                } else if (e.getKeyChar() == KeyEvent.VK_ESCAPE) {
                    cancelEdit();
                }
            }

            public void keyTyped(KeyEvent e) { }

            public void keyReleased(KeyEvent e) { }
        });
    }

    public void setCommand(Command cmd) {
        editingCmd = cmd;
        editor.setText(cmd.getAnnotation());
    }

    public void stopEdit() {
        if (editingCmd != null) {
            editingCmd.setAnnotation(editor.getText());
            hide();
            fireEditingStopped();
        }
    }

    public void cancelEdit() {
        hide();
        fireEditingCanceled();
    }

    @Override
    public void doLayout() {
        Dimension size = editor.getPreferredSize();
        editor.setBounds(15, 0, size.width, size.height);
    }

    @Override
    public Dimension getPreferredSize() {
        Dimension d = editor.getPreferredSize();
        d.setSize(d.width + 15, d.height + 15);
        return d;
    }

    public void show(Point p) {
        final Window window = SwingUtilities.getWindowAncestor(owner);
        Container glassPane = (Container) owner.getRootPane().getGlassPane();
        glassPane.setLayout(null);
        Dimension d = getPreferredSize();
        setBounds(p.x, p.y - d.height, d.width, d.height);
        glassPane.add(this);
        glassPane.setVisible(true);
        window.validate();
        window.repaint();
    }

    public void focus() {
        editor.requestFocus();
    }

    public void hide() {
        Container glassPane = (Container) owner.getRootPane().getGlassPane();
        glassPane.remove(this);
        glassPane.repaint();
        glassPane.setVisible(false);
        editor.setText("");
    }

    @Override
    protected void paintComponent(Graphics g) {
        Dimension size = this.getSize();
        Graphics2D g2d = (Graphics2D) g;
        GeneralPath path = new GeneralPath();
        path.moveTo(0, size.height);
        path.lineTo(8, size.height - 2);
        path.lineTo(2, size.height - 8);
        path.lineTo(0, size.height);
        g2d.fill(path);
        g2d.setStroke(new BasicStroke(2));
        g2d.setColor(Color.black);
        g2d.drawLine(0, size.height, 15, size.height - 15);
    }

    public void addCellEditorListener(CellEditorListener l) {
        listenerList.add(CellEditorListener.class, l);
    }

    public void removeCellEditorListener(CellEditorListener l) {
        listenerList.remove(CellEditorListener.class, l);
    }

    public CellEditorListener[] getCellEditorListeners() {
        return (CellEditorListener[]) listenerList.getListeners(
                CellEditorListener.class);
    }

    protected void fireEditingStopped() {
        // Guaranteed to return a non-null array
        Object[] listeners = listenerList.getListenerList();
        // Process the listeners last to first, notifying
        // those that are interested in this event
        for (int i = listeners.length - 2; i >= 0; i -= 2) {
            if (listeners[i] == CellEditorListener.class) {
                // Lazily create the event:
                if (changeEvent == null)
                    changeEvent = new ChangeEvent(this);
                ((CellEditorListener) listeners[i + 1]).editingStopped(changeEvent);
            }
        }
    }

    protected void fireEditingCanceled() {
        // Guaranteed to return a non-null array
        Object[] listeners = listenerList.getListenerList();
        // Process the listeners last to first, notifying
        // those that are interested in this event
        for (int i = listeners.length - 2; i >= 0; i -= 2) {
            if (listeners[i] == CellEditorListener.class) {
                // Lazily create the event:
                if (changeEvent == null)
                    changeEvent = new ChangeEvent(this);
                ((CellEditorListener) listeners[i + 1]).editingCanceled(changeEvent);
            }
        }
    }

    private class AnnotationEditPaneBorder extends AbstractBorder {
        @Override
        public boolean isBorderOpaque() {
            return true;
        }

        @Override
        public Insets getBorderInsets(Component c) {
            return new Insets(2, 2, 4, 4);
        }

        @Override
        public void paintBorder(Component c, Graphics g, int x, int y, int width, int height) {
            Graphics2D g2d = (Graphics2D) g;
            g2d.setStroke(new BasicStroke(2));
            g2d.drawRect(x, y, width - 2, height - 2);
            g2d.drawLine(x + 6, y + height, x + width, y + height);
            g2d.drawLine(x + width, y + 6, x + width, y + height);
        }
    }
}
